﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DelayGestureController.cs" company="arvystate.net">
//   arvystate.net
// </copyright>
// <summary>
//   The delay gesture controller.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace PresentationAid.Lib.GestureControllers
{
    using System;

    using Microsoft.Kinect;

    using NLog;

    using PresentationAid.Lib.Enums;
    using PresentationAid.Lib.Gestures;

    /// <summary>
    /// The delay gesture controller.
    /// </summary>
    public abstract class DelayGestureController : IGestureController
    {
        #region Static Fields

        /// <summary>
        /// The logger.
        /// </summary>
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        #endregion

        #region Fields

        /// <summary>
        /// The last recognition.
        /// </summary>
        private DateTime lastRecognition;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="DelayGestureController"/> class. 
        /// Default delay is set to 1000 milliseconds
        /// </summary>
        protected DelayGestureController()
        {
            Logger.Trace("Init: DelayGestureController - Delay: 1000");

            this.Delay = 1000;
        }

        #endregion

        #region Public Events

        /// <summary>
        /// The gesture recognized.
        /// </summary>
        public event GestureEventHandler GestureRecognized;

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the delay to execute commands, as it is physically hard to wave 10 times in 1 microsecond. 
        /// Gestures received in delay are discarded.
        /// </summary>
        public int Delay { get; set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The recognize.
        /// </summary>
        /// <param name="frame">
        /// The frame.
        /// </param>
        public abstract void Recognize(SkeletonFrame frame);

        #endregion

        #region Methods

        /// <summary>
        /// Execute gesture past delay
        /// </summary>
        /// <param name="command">
        /// Command to execute
        /// </param>
        /// <param name="trackingId">
        /// Tracking Id of the skeleton that did the gesture
        /// </param>
        protected void ExecuteGestureRecognized(GestureCommand command, int trackingId)
        {
            // Check if we are past delay
            if (!((DateTime.Now - this.lastRecognition).TotalMilliseconds > this.Delay))
            {
                Logger.Debug(
                    "MethodDetail: ExecuteGestureRecognited - Delayed, Recognizer: {0}, Command: {1}, TrackingId: {2}, Delay: {3}", 
                    this.GetType().Name, 
                    command.ToString(), 
                    trackingId, 
                    this.Delay);

                return;
            }

            Logger.Info(
                "MethodDetail: ExecuteGestureRecognited - Executed, Recognizer: {0}, Command: {1}, TrackingId: {2}", 
                this.GetType().Name, 
                command.ToString(), 
                trackingId);

            this.lastRecognition = DateTime.Now;

            this.GestureRecognized(this, new GestureEventArgs(command, trackingId));
        }

        #endregion
    }
}